{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.6.6"
    },
    "colab": {
      "name": "1.1.ipynb",
      "provenance": []
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "75fw804auz_t",
        "colab_type": "text"
      },
      "source": [
        "第一课的代码非常的简单,\n",
        "\n",
        "就是给大家展示一下rule-based的玩法,\n",
        "\n",
        "以及几个角度的升级。\n",
        "\n",
        "首先，我们看一个"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9-R7ZNHCuz_u",
        "colab_type": "text"
      },
      "source": [
        "### 最基础版本的rule-base机器人"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "X_v31bm4uz_v",
        "colab_type": "text"
      },
      "source": [
        "基本就是小学生级别的，问什么，答什么"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "WUVdQcXjuz_w",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 170
        },
        "outputId": "fb054030-b37f-4613-804f-0647971dca33"
      },
      "source": [
        "import random\n",
        "\n",
        "#打招呼\n",
        "grettings=['hola','hello','hi','Hi','hey!','hey']\n",
        "# 回复打招呼\n",
        "random_gretting=random.choice(grettings)\n",
        "\n",
        "#对于“你怎么样？”这个问题的回答\n",
        "question = ['How are you?','How are you doing?']\n",
        "# 我很好\n",
        "responses = ['Okay',\"I'm fine\"]\n",
        "# 随机选择一个回\n",
        "random_response=random.choice(responses)\n",
        "\n",
        "#机器人跑起来\n",
        "\n",
        "while True:\n",
        "    userInput=input(\">>>\")\n",
        "    if userInput in grettings:\n",
        "        print(random_gretting)\n",
        "    elif userInput in question:\n",
        "        print(random_response)\n",
        "    # 除非你说‘拜拜’\n",
        "    elif userInput == 'bye':\n",
        "        break\n",
        "    else:\n",
        "        print('I did not understand what you said')"
      ],
      "execution_count": 1,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            ">>>hi\n",
            "Hi\n",
            ">>>how are u\n",
            "I did not understand what you said\n",
            ">>>how are you\n",
            "I did not understand what you said\n",
            ">>>How are you?\n",
            "Okay\n",
            ">>>bye\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "w3FQrwcJuz_3",
        "colab_type": "text"
      },
      "source": [
        "### 升级1：\n",
        "\n",
        "显然 这样的rule太弱智了，我们需要更好一点的“精准对答”\n",
        "\n",
        "比如\n",
        "\n",
        "透过关键词来判断这句话的意图是什么（intents）"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "SePJ8Uecuz_4",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 170
        },
        "outputId": "b7b235aa-1134-4b46-c0ce-a3e5492018ac"
      },
      "source": [
        "import nltk\n",
        "from nltk import word_tokenize\n",
        "nltk.download('punkt')\n",
        "import random\n",
        "\n",
        "# 打招呼\n",
        "greetings = ['hola', 'hello', 'hi', 'Hi', 'hey!','hey']\n",
        "# 回复打招呼\n",
        "random_greeting = random.choice(greetings)\n",
        "\n",
        "\n",
        "# 对于“假期”的话题关键词\n",
        "question = ['break','holiday','vacation','weekend']\n",
        "# 回复假期话题\n",
        "responses = ['It was nice! I went to Paris',\"Sadly, I just stayed at home\"]\n",
        "# 随机选一个回\n",
        "random_response = random.choice(responses)\n",
        "\n",
        "#机器人跑起来\n",
        "while True:\n",
        "    userInput=input(\">>>\")\n",
        "    #清理一下输入，看看都有哪些词\n",
        "    cleaned_input=word_tokenize(userInput)\n",
        "    #这里，我们比较一下关键词，确定他属于哪个问题\n",
        "    if not set(cleaned_input).isdisjoint(greetings):\n",
        "        print(random_gretting)\n",
        "    elif not set(cleaned_input).isdisjoint(question):\n",
        "        print(random_response)\n",
        "    #除非你说拜拜\n",
        "    elif userInput =='bye':\n",
        "        break\n",
        "    else:\n",
        "        print('I did not understand what you said')"
      ],
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "[nltk_data] Downloading package punkt to /root/nltk_data...\n",
            "[nltk_data]   Unzipping tokenizers/punkt.zip.\n",
            ">>>hi\n",
            "Hi\n",
            ">>>how was your hlliday?\n",
            "I did not understand what you said\n",
            ">>>how wa your holiday\n",
            "Sadly, I just stayed at home\n",
            ">>>bye\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "a_6wG2WMw1HW",
        "colab_type": "text"
      },
      "source": [
        "#### nltk.word_tokenize\n",
        "* 主要是用来分词\n",
        "* 看下面的例子"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "MIWfFRIxwe0U",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "from nltk import word_tokenize\n",
        "paragraph = \"Life  is  not  easy  for  any  of  us. We  must  work,and  above  all \\\n",
        " we must  believe  in  ourselves. We  must  believe  that  each  one  of  us  is  \\\n",
        " able to  do  something well, and  that, when  we  discover  what  this  something  is,\\\n",
        " we  must  work  hard  at  it  until we  succeed.\"\n",
        "words_list=nltk.word_tokenize(paragraph)\n",
        "#words_list"
      ],
      "execution_count": 6,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "HzX3QqkMuz_9",
        "colab_type": "text"
      },
      "source": [
        "大家大概能发现，这依旧是文字层面的“精准对应”。\n",
        "\n",
        "现在主流的研究方向，是做到语义层面的对应。\n",
        "\n",
        "比如，“肚子好饿哦”， “饭点到了”\n",
        "\n",
        "都应该表示的是要吃饭了的意思。\n",
        "\n",
        "在这个层面，就需要用到`word vector`之类的`embedding`方法，\n",
        "\n",
        "这部分内容 日后的课上会涉及到。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "feSMOAm0xhsB",
        "colab_type": "text"
      },
      "source": [
        "### 升级2：\n",
        "\n",
        "光是会BB还是不行，得有知识体系！才能解决用户的问题。\n",
        "\n",
        "我们可以用各种数据库，建立起一套体系，然后通过搜索的方式，来查找答案。\n",
        "\n",
        "比如，最简单的就是Python自己的graph数据结构来搭建一个“地图”。\n",
        "\n",
        "依据这个地图，我们可以清楚的找寻从一个地方到另一个地方的路径，\n",
        "\n",
        "然后作为回答，反馈给用户。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Fh0-H4Ygxl0e",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# 建立一个基于目标行业的database\n",
        "# 比如 这里我们用python自带的graph\n",
        "\n",
        "graph = {'上海': ['苏州', '常州'],\n",
        "         '苏州': ['常州', '镇江'],\n",
        "         '常州': ['镇江'],\n",
        "         '镇江': ['常州'],\n",
        "         '盐城': ['南通'],\n",
        "         '南通': ['常州']}\n",
        "\n",
        "# 明确如何找到从A到B的路径\n",
        "def find_path(start,end,path=[]):\n",
        "  path=path+[start]\n",
        "  if start==end:\n",
        "    return path\n",
        "  if start not in graph:\n",
        "    return None\n",
        "  for node in graph[start]:\n",
        "    if node not in path:\n",
        "      newpath=find_path(node,end,path)\n",
        "      if newpath:return newpath\n",
        "  return None"
      ],
      "execution_count": 7,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "u0CjAbgTxo3e",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        },
        "outputId": "5d8f4bff-87f7-4901-f74c-22004289207e"
      },
      "source": [
        "find_path('上海','镇江')"
      ],
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "['上海', '苏州', '常州', '镇江']"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 8
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "gAemYou1xryP",
        "colab_type": "text"
      },
      "source": [
        "同样的构建知识图谱的玩法，\n",
        "\n",
        "也可以使用一些Logic Programming，比如上个世纪学AI的同学都会学的Prolog。\n",
        "\n",
        "或者比如，python版本的prolog：PyKE。\n",
        "\n",
        "他们可以构建一种复杂的逻辑网络，让你方便提取信息，\n",
        "\n",
        "而不至于需要你亲手code所有的信息:\n",
        "\n",
        "* son_of(bruce, thomas, norma)\n",
        "* son_of(fred_a, thomas, norma)\n",
        "* son_of(tim, thomas, norma)\n",
        "* daughter_of(vicki, thomas, norma)\n",
        "* daughter_of(jill, thomas, norma)\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "759D2Xasxwlw",
        "colab_type": "text"
      },
      "source": [
        "### 升级3：\n",
        "\n",
        "任何行业，都分个前端后端。\n",
        "\n",
        "AI也不例外。\n",
        "\n",
        "我们这里讲的算法，都是后端跑的。\n",
        "\n",
        "那么， 为了做一个靠谱的前端，很多项目往往也需要一个简单易用，靠谱的前端。\n",
        "\n",
        "比如，这里，利用Google的API，写一个类似钢铁侠Tony的语音小秘书Jarvis：\n",
        "\n",
        "我们先来看一个最简单的说话版本。\n",
        "\n",
        "利用`gTTs(Google Text-to-Speech API)`, 把文本转化为音频。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Ya-zx4xHx2Qd",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 34
        },
        "outputId": "435acb22-e369-4e3b-9e47-e2930caa6f95"
      },
      "source": [
        "#! pip install gtts\n",
        "from gtts import gTTS\n",
        "import os\n",
        "# 把文字转换为音频\n",
        "tts=gTTS(text='您好，我是您的私人助手，我叫小辣椒',lang='zh-tw')\n",
        "tts.save('hello.mp3')\n",
        "os.system('mpg321 hello.mp3')"
      ],
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "32512"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 11
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "3BbhnwmjyIXr",
        "colab_type": "text"
      },
      "source": [
        "同理，\n",
        "\n",
        "有了文本到语音的功能，\n",
        "\n",
        "我们还可以运用Google API读出Jarvis的回复：\n",
        "\n",
        "（注意：这里需要你的机器安装几个库 SpeechRecognition, PyAudio 和 PySpeech）"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "EESjtFvWx41_",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "#!pip install SpeechRecognition\n",
        "#! sudo apt-get install libasound-dev portaudio19-dev libportaudio2 libportaudiocpp0\n",
        "#! pip install pyaudio\n",
        "import speech_recognition as sr\n",
        "from time import ctime\n",
        "import time\n",
        "import os\n",
        "from gtts import gTTS\n",
        "import sys"
      ],
      "execution_count": 17,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "hKkl8xxOu0AC",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# 讲出来AI的话\n",
        "def speak(audioString):\n",
        "    print(audioString)\n",
        "    tts = gTTS(text=audioString, lang='en')\n",
        "    tts.save(\"audio.mp3\")\n",
        "    os.system(\"mpg321 audio.mp3\")\n",
        "\n",
        "# 录下来你讲的话\n",
        "def recordAudio():\n",
        "    # 用麦克风记录下你的话\n",
        "    r = sr.Recognizer()\n",
        "    with sr.Microphone() as source:\n",
        "        audio = r.listen(source)\n",
        " \n",
        "    # 用Google API转化音频\n",
        "    data = \"\"\n",
        "    try:\n",
        "        data = r.recognize_google(audio)\n",
        "        print(\"You said: \" + data)\n",
        "    except sr.UnknownValueError:\n",
        "        print(\"Google Speech Recognition could not understand audio\")\n",
        "    except sr.RequestError as e:\n",
        "        print(\"Could not request results from Google Speech Recognition service; {0}\".format(e))\n",
        " \n",
        "    return data\n",
        "\n",
        "# 自带的对话技能（rules）\n",
        "def jarvis():\n",
        "    \n",
        "    while True:\n",
        "        \n",
        "        data = recordAudio()\n",
        "\n",
        "        if \"how are you\" in data:\n",
        "            speak(\"I am fine\")\n",
        "\n",
        "        if \"what time is it\" in data:\n",
        "            speak(ctime())\n",
        "\n",
        "        if \"where is\" in data:\n",
        "            data = data.split(\" \")\n",
        "            location = data[2]\n",
        "            speak(\"Hold on Tony, I will show you where \" + location + \" is.\")\n",
        "            os.system(\"open -a Safari https://www.google.com/maps/place/\" + location + \"/&amp;\")\n",
        "\n",
        "        if \"bye\" in data:\n",
        "            speak(\"bye bye\")\n",
        "            break\n",
        "\n",
        "# 初始化\n",
        "time.sleep(2)\n",
        "speak(\"Hi Tony, what can I do for you?\")\n",
        "\n",
        "# 跑起\n",
        "jarvis()"
      ],
      "execution_count": 19,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "_6LEQScCy-qq",
        "colab_type": "text"
      },
      "source": [
        "Hi Tony, what can I do for you?\n",
        "\n",
        "You said: how are you\n",
        "\n",
        "I am fine\n",
        "\n",
        "You said: what time is it now\n",
        "\n",
        "Fri Apr  7 18:16:54 2017\n",
        "\n",
        "You said: where is London\n",
        "\n",
        "Hold on Tony, I will show you where London is.\n",
        "\n",
        "You said: ok bye bye\n",
        "\n",
        "bye bye"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9gt558-vzA-v",
        "colab_type": "text"
      },
      "source": [
        "不仅仅是语音前端。\n",
        "\n",
        "包括应用场景：微信，slack，Facebook Messager，等等 都可以把我们的ChatBot给integrate进去。\n",
        "\n",
        "这部分内容也会在我们课程的后面阶段带给大家。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "1m_aGzjry6TI",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "NWMo2kI5u0AH",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Fv41wb6ju0AL",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "041qjzYWu0AS",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "2jVkZUoau0AX",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Ik-KkgkCu0Ae",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "262TnULRu0Ai",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "OolYCQfAu0Am",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "LeZo7Incu0Ar",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "7eXv5EO3u0Av",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "mIiAVXKCu0Az",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "I4nJWDEUu0A4",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "CgKSJb7wu0A8",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    }
  ]
}